<template>
  <Menu
    :selectedKeys="selectedKeys"
    :defaultSelectedKeys="defaultSelectedKeys"
    :mode="mode"
    :openKeys="getOpenKeys"
    :inlineIndent="inlineIndent"
    :theme="theme"
    @open-change="handleOpenChange"
    :class="getMenuClass"
    @click="handleMenuClick"
    :subMenuOpenDelay="0.1"
    v-bind="getInlineCollapseOptions"
  >
    <template v-for="item in items" :key="item.path">
      <BasicSubMenuItem :item="item" :theme="theme" :isHorizontal="isHorizontal" />
    </template>
  </Menu>
</template>
<script lang="ts">
import type { MenuState } from "./Types";
import { computed, defineComponent, unref, reactive, watch, toRefs, ref } from "vue";
import { Menu } from "ant-design-vue";
import BasicSubMenuItem from "./components/BasicSubMenuItem.vue";
import { MenuModeEnum, MenuTypeEnum } from "/@/enums/MenuEnum";
import { useOpenKeys } from "./UseOpenKeys";
import { RouteLocationNormalizedLoaded, useRouter } from "vue-router";
import { isFunction } from "/@/utils/Is";
import { basicProps } from "./Props";
import { useMenuSetting } from "/@/hooks/setting/UseMenuSetting";
import { REDIRECT_NAME } from "/@/router/Constant";
import { useDesign } from "/@/hooks/web/UseDesign";
import { getCurrentParentPath } from "/@/router/menus";
import { listenerRouteChange } from "/@/logics/mitt/RouteChange";
import { getAllParentPath } from "/@/router/helper/MenuHelper";

export default defineComponent({
  name: "BasicMenu",
  components: {
    Menu,
    BasicSubMenuItem
  },
  props: basicProps,
  emits: ["menuClick"],
  setup(props, { emit }) {
    const isClickGo = ref(false);
    const currentActiveMenu = ref("");

    const menuState = reactive<MenuState>({
      defaultSelectedKeys: [],
      openKeys: [],
      selectedKeys: [],
      collapsedOpenKeys: []
    });

    const { prefixCls } = useDesign("basic-menu");
    const { items, mode, accordion } = toRefs(props);

    const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting();

    const { currentRoute } = useRouter();

    const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
      menuState,
      items,
      mode as any,
      accordion
    );

    const getIsTopMenu = computed(() => {
      const { type, mode } = props;

      return (
        (type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
        (props.isHorizontal && unref(getSplit))
      );
    });

    const getMenuClass = computed(() => {
      const align = props.isHorizontal && unref(getSplit) ? "start" : unref(getTopMenuAlign);
      return [
        prefixCls,
        `justify-${align}`,
        {
          [`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
          [`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu)
        }
      ];
    });

    const getInlineCollapseOptions = computed(() => {
      const isInline = props.mode === MenuModeEnum.INLINE;

      const inlineCollapseOptions: { inlineCollapsed?: boolean } = {};
      if (isInline) {
        inlineCollapseOptions.inlineCollapsed = props.mixSider ? false : unref(getCollapsed);
      }
      return inlineCollapseOptions;
    });

    listenerRouteChange((route) => {
      if (route.name === REDIRECT_NAME) return;
      handleMenuChange(route);
      currentActiveMenu.value = route.meta?.currentActiveMenu as string;

      if (unref(currentActiveMenu)) {
        menuState.selectedKeys = [unref(currentActiveMenu)];
        setOpenKeys(unref(currentActiveMenu));
      }
    });

    !props.mixSider &&
    watch(
      () => props.items,
      () => {
        handleMenuChange();
      }
    );

    async function handleMenuClick({ key }: { key: string; keyPath: string[] }) {
      const { beforeClickFn } = props;
      if (beforeClickFn && isFunction(beforeClickFn)) {
        const flag = await beforeClickFn(key);
        if (!flag) return;
      }
      emit("menuClick", key);

      isClickGo.value = true;
      menuState.selectedKeys = [key];
    }

    async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
      if (unref(isClickGo)) {
        isClickGo.value = false;
        return;
      }
      const path =
        (route || unref(currentRoute)).meta?.currentActiveMenu ||
        (route || unref(currentRoute)).path;
      setOpenKeys(path);
      if (unref(currentActiveMenu)) return;
      if (props.isHorizontal && unref(getSplit)) {
        const parentPath = await getCurrentParentPath(path);
        menuState.selectedKeys = [parentPath];
      } else {
        const parentPaths = await getAllParentPath(props.items, path);
        menuState.selectedKeys = parentPaths;
      }
    }

    return {
      handleMenuClick,
      getInlineCollapseOptions,
      getMenuClass,
      handleOpenChange,
      getOpenKeys,
      ...toRefs(menuState)
    };
  }
});
</script>
<style lang="less">
@import './index.less';
</style>
